<template>
  <component
    ref="formEl"
    :is="formRegister ? 'w-form-element' : 'div'"
    v-bind="
      formRegister && {
        validators,
        inputValue: checkboxItems.some((item) => item.isChecked),
        disabled,
      }
    "
    v-model:valid="valid"
    @reset="reset"
    :column="!inline"
    :class="classes"
  >
    <w-checkbox
      v-for="(item, i) in checkboxItems"
      :key="i"
      :model-value="item.isChecked"
      :name="`${name || `w-checkboxes--${_.uid}`}[]`"
      :label="item.label"
      :label-on-left="labelOnLeft"
      :color="item.color"
      :round="round"
      @update:model-value="toggleCheck(item, $event)"
      :disabled="disabled || null"
      :readonly="readonly || null"
      @focus="$emit('focus', $event)"
      :class="{ mt1: !inline && i }"
    >
      <slot v-if="$slots.item" name="item" :item="item"></slot>
      <div v-else-if="item.label" v-html="item.label"></div>
    </w-checkbox>
  </component>
</template>
<script>
  import { ref, reactive, computed } from "vue";

  export default {
    name: "w-checkboxes",

    props: {
      items: { type: Array, required: true }, // All the possible options.
      modelValue: { type: Array }, // v-model on selected option.
      labelOnLeft: { type: Boolean },
      itemLabelKey: { type: String, default: "label" },
      itemValueKey: { type: String, default: "value" },
      itemColorKey: { type: String, default: "color" }, // Support a different color per item.
      inline: { type: Boolean },
      round: { type: Boolean },
      color: { type: String, default: "primary" },
      // Also name, disabled, readonly, required and validators in the mixin.
      name: { type: String }, // When sending data through form.
      disabled: { type: Boolean },
      readonly: { type: Boolean },
      required: { type: Boolean },
      validators: { type: Array },
    },

    emits: ["input", "update:modelValue", "focus"],
    inject: { formRegister: { default: null } },
    provide() {
      // Disable w-form-el wrapping in each w-checkbox when inside a w-checkboxes component that already
      // does it.
      // Don't do a simple prop that can be turned on and off by user.
      return { wCheckboxes: true };
    },

    setup(props, ctx) {
      const valid = ref(null);
      const checkboxItems = computed(() => {
        return (props.items || []).map((item, i) => {
          const itemValue =
            item[props.itemValueKey] === undefined
              ? item[props.itemLabelKey] || i
              : item[props.itemValueKey];

          return reactive({
            ...item,
            label: item[props.itemLabelKey],
            index: i,
            value: itemValue, // If no value is set then add one to prevent error.
            color: item[props.itemColorKey] || props.color,
            isChecked: props.modelValue && props.modelValue.includes(itemValue),
          });
        });
      });
      const classes = computed(() => {
        return [
          "w-checkboxes",
          `w-checkboxes--${props.inline ? "inline" : "column"}`,
        ];
      });

      function reset() {
        checkboxItems.value.forEach((item) => (item.isChecked = null));
        ctx.emit("update:modelValue", []);
        ctx.emit("input", []);
      }

      function toggleCheck(checkbox, isChecked) {
        checkbox.isChecked = isChecked;
        const selection = checkboxItems.value
          .filter((item) => item.isChecked)
          .map((item) => item.value);

        ctx.emit("update:modelValue", selection);
        ctx.emit("input", selection);
      }

      return {
        valid,
        checkboxItems,
        classes,
        reset,
        toggleCheck,
      };
    },
  };
</script>
